#include <string.h>
#include"../headers/groups.h"

	/* Fonctions pour la structure list_groups */
	void createList(struct list_groups *list, struct server_msg msg){
		list->nGroup = 0;
		list->msg=msg;
		sendMSG(list->msg.fd, "CreateList() function:: new list created successfully! ");
	}

	int addGroup(struct list_groups *list, struct groups newGroupe)
	{
		/* Vérifie que le groupe ne s'y trouve pas déja*/
		struct groups *select=selectGroup(list, newGroupe.name);
		if(select!=NULL) return 0;

		if(list->nGroup<maxGroup) /* verifie que la liste n'est pas pleine */
		{
			list->list[list->nGroup]=newGroupe; /* ajout du groupe dans la fin de la liste */
			list->nGroup++; /* mise a jour du nombre de groupe <=> de la taille de la list */
			sendMSG(list->msg.fd, "AddGroup() function:: Group added successfully! ");
			return 1;
		}
		else
		{	
			char buff[200];
			strcpy(buff, "AddGroup() function:: max groups allowed=");
			char *str;
			sprintf(str, "%d", maxGroup);
			strcat(buff, str);
			strcat(buff, " !");
			sendMSG(list->msg.fd, buff);
			return 0; /* une erreur s'est produite, on renvoie 0 */
		}
	}

	int rmGroup(struct list_groups *list,char* name)
	{ 
		if(list->nGroup>0)/* verifie qu'il y existe encore au moins un groupe dans la liste */
		{
			int position=list->nGroup-1;/* emplacement du curseur dans la list pour la recherche */
			int inList=0;/* permet d'indiquer si le groupe est dans la liste (inList=1) ou non (inList=0) */
			
			while(position>=0 && inList==0){/* recherche la position du groupe dans la liste */
				if(strcmp(list->list[position].name,name)==0){/* si le groupe ce trouvant a la position du curseur a le nom rechercher */
					inList=1;/* on a trouver le groupe */
				}
				else {
					position--;/* on passe au groupe suivant */
				}
			}

			if(inList==0) { /* on n'a pas trouver le groupe */
				char buff[200];
				sprintf(buff, "RmGroup() function:: Group with name=%s not found", name);
				sendMSG(list->msg.fd, buff);
				return -1; /* renvoie du numeros d'erreur */
			}
			else {
				int cpt;
				for(cpt=position; cpt<list->nGroup-1; cpt++){
					/* mise a jour de la list */
					list->list[cpt]=list->list[cpt+1]; /* verifier si ca marche ... */
				}
				list->nGroup--; /* mise a jour du nombre de groupe */
				char buff[200];
				sprintf(buff, "SelectGroup() function:: group found at position=%d and removed successfully! ", position);
				sendMSG(list->msg.fd, buff);
				return position;
			}
		}
		else
		{
			sendMSG(list->msg.fd, "RmGroup() function:: listGroup empty! ");
			return -1;
		}
	}

	void cleanListGroup(struct list_groups *list)
	{
		list->nGroup=0;
		sendMSG(list->msg.fd, "CleanListGroup() function:: listgroup clear! ");
		/* tester */
	}

	struct groups* selectGroup(struct list_groups *list, char* name)
	{
		char buff[200];
		if(list->nGroup>0){
			int position=list->nGroup-1;/*emplacement du curseur dans la list pour la recherche */
			int inList=0;/* permet d'indiquer si le groupe est dans la liste (inList=1) ou non (inList=0) */
			while(position>=0 && inList==0){/* recherche la position du groupe dans la liste */
				if(strcmp(list->list[position].name,name)==0){/* si le groupe ce trouvant a la position du curseur a le nom rechercher */
					inList=1;/* on a trouver le groupe */
				}
				else {
					position--;/* on passe au groupe suivant */
				}
			}
			if(inList==0) { /* on n'a pas trouver le groupe */
				sprintf(buff, "RmGroup() function:: Group with name=%s not found", name);
				sendMSG(list->msg.fd, buff);
				return NULL; /* renvoie du numeros d'erreur */
			}
			else {
				sprintf(buff, "SelectGroup() function:: group found at position=%d and selected successfully! ", position);
				sendMSG(list->msg.fd, buff);
				return &list->list[position];
			}
		}
		else{
			sendMSG(list->msg.fd, "SelectGroup() function:: groupList empty! ");
			return NULL;
		}
	
	}


	/* Fonctions pour la structure groups */
	void createGroup(struct groups *newGroup, char* name, struct user* master, struct server_msg msg)
	{
		strcpy(newGroup->name, name);//affect le nom passer en parametre
		initDevice(200,200, &(newGroup->device) );//utilisation de la fonction initDevice pour creer une nouvelle device pour le groupe
		newGroup->nUser=0;//initialisse le nombre d'utilisateur dans le groupe à 0(zero), le master est compter seul 
		newGroup->master=*master;//affectation du master du groupe, on donne la meme adresse du pointeur, afin de ne pas recopier l'information
		newGroup->msg=msg;

		char buff[200];
		sprintf(buff, "CreateGroup() function:: new group name=%s master=%s was create successfully! ", name, master->name);
		sendMSG(newGroup->msg.fd, buff);
	}

	int addUser(struct groups *grp, struct user newUser)
	{
		char buff[200];

		/*On vérifie que l'utilisateur ne se trouve déja pas dans le groupe*/
		struct user *select=selectUserByName(grp, newUser.name);
		if(select!=NULL) return 0;

		if(grp->nUser<maxUser) /* verifie que la liste n'est pas pleine */
		{
			grp->list[grp->nUser]=newUser; /* ajout d'un utilisateur a la fin de la liste */
			grp->nUser++; /* mise a jour du nombre de'utilisateur <=> de la taille de la list */
                        sprintf(buff, "AddUser() function:: user=%s added in group=%s !", newUser.name, grp->name);
                        sendMSG(grp->msg.fd, buff);
			return 1;
		}
		else
		{
                	sprintf(buff, "AddUser() function:: max user allowed=%d! ", maxUser);
			sendMSG(grp->msg.fd, buff);
			return 0; /* une erreur s'est produite, on renvoie 0 */
		}
	}

	int rmUser(struct groups *grp, struct user oldUser)
	{
		if(grp->nUser>0)/* verifie qu'il y existe encore au moins un utilisateur dans la liste */
		{
			int position=grp->nUser-1;/* emplacement du curseur dans la list pour la recherche */
			int inList=0;/* permet d'indiquer si l'utilisateur est dans la liste (inList=1) ou non (inList=0) */
			while(position>=0 && inList==0){/* recherche la position de l'utilisateur dans la liste */
				if(grp->list[position].id==oldUser.id){/* si l'utilisateur ce trouvant a la position du curseur a le nom rechercher */
					inList=1;/* on a trouver l'utilisateur */
				}
				else {
					position--;/* on passe a l'utilisateur suivant */
				}
			}

			if(inList==0) { /* on n'a pas trouver l'utilisateur */
				char buff[200];
				sprintf(buff, "RmUser() function:: User with name=%s not found! ", oldUser.name);
                                sendMSG(grp->msg.fd, buff);
				return -1; /* renvoie du numeros d'erreur */
			}
			else {
				int cpt;
				for(cpt=position; cpt<grp->nUser-1; cpt++){
					/* mise a jour de la list */
					grp->list[cpt]=grp->list[cpt+1]; /* verifier si ca marche ... */
				}
				grp->nUser--; /* mise a jour du nombre d'utilisateur */
				
				char buff[200];
				sprintf(buff, "RmUser() function:: user found  at position=%d  in group=%s and will be remove! ", position, grp->name);
                                sendMSG(grp->msg.fd, buff);
				return position;
			}
		}
		else
		{
			sendMSG(grp->msg.fd, "RmUser() function:: group empty !");
			return -1;
		}
	}

	void cleanListUser(struct groups *grp)
	{
		grp->nUser=0;
		char buff[200];
		strcpy(buff, "CleanListUser() function::  userList from group=");
		strcat(buff, grp->name);
		strcat(buff, " clear! ");
	        sendMSG(grp->msg.fd, buff);
		/* tester */
	}

	struct user* selectUserBySD(struct groups *grp, int sd)
	{
		if(grp->nUser>0){
			int position=grp->nUser-1;/*emplacement du curseur dans la list pour la recherche */
			int inList=0;/* permet d'indiquer si l'utilisateur est dans la liste (inList=1) ou non (inList=0) */
			while(position>=0 && inList==0){/* recherche la position de l'utilisateur dans la liste */
				if(grp->list[position].sd==sd){/* si l'utilisateur ce trouvant a la position du curseur a le nom rechercher */
					inList=1;/* on a trouver l'utilisateur */
				}
				else {
					position--;/* on passe a l'utilisateur suivant */
				}
			}
			if(inList==0) { /* on n'a pas trouver l'utilisateur */
				sendMSG(grp->msg.fd, "SelectUser() function:: no user found! ");
				return NULL; /* renvoie du numeros d'erreur */
			}
			else {
				char buff[200];
				sprintf(buff, "selectUserBySD() function:: user found  at position=%d  in group=%s and will be selected! ", position, grp->name);
                                sendMSG(grp->msg.fd, buff);
				return &grp->list[position];
			}
		}
		else{
			sendMSG(grp->msg.fd, "SelectUser() function:: userList empty! ");
			return NULL;
		}
	}
	
	struct user* selectUserByName(struct groups *grp, char *n)
	{
		if(grp->nUser>0){
			char name[100];
			strcpy(name, n);

			int position=grp->nUser-1;/*emplacement du curseur dans la list pour la recherche */
			int inList=0;/* permet d'indiquer si l'utilisateur est dans la liste (inList=1) ou non (inList=0) */
			while(position>=0 && inList==0){/* recherche la position de l'utilisateur dans la liste */
				if(strcmp(grp->list[position].name, name)==0){/* si l'utilisateur ce trouvant a la position du curseur a le nom rechercher */

					inList=1;/* on a trouver l'utilisateur */
				}
				else {
					position--;/* on passe a l'utilisateur suivant */
				}
			}
			if(inList==0) { /* on n'a pas trouver l'utilisateur */
				sendMSG(grp->msg.fd, "SelectUser() function:: no user found! ");
				return NULL; /* renvoie du numeros d'erreur */
			}
			else {
				char buff[200];
                                sprintf(buff, "selectUserByName() function:: user found  at position=%d  in group=%s and will be selected! ", position, grp->name);
                                sendMSG(grp->msg.fd, buff);
				return &grp->list[position];
			}
		}
		else{
			sendMSG(grp->msg.fd, "SelectUser() function:: userList empty! ");
			return NULL;
		}
	}

	void printUsers(struct groups grp, struct server_msg msg)
	{      	
		char buff[100];
		sprintf(buff, "PrintUser() function:: Group=%s number of user=%d : ", grp.name, grp.nUser);
		sendMSG(msg.fd, buff);

		int j;
		for(j=0; j<grp.nUser; ++j)
		{
			sprintf(buff, "User n°%d name=%s id=%d ip=%s", j, grp.list[j].name, grp.list[j].id, inet_ntoa(grp.list[j].addr.sin_addr));
			sendMSG(msg.fd, buff);		
		}
	}

